#include <iostream>
#include <iterator>
#include <cstring>
#include <typeinfo>
#include <algorithm>
#include <array>
#include <vector>
#include <tuple>
#include <functional>

using namespace std;

std::tuple<int, double> returnTuple()
{
    std::tuple<int, double> s{ 5, 6.7 };
    return s;
}

int foo()
{
    return 5;
}

using OtherName = int(*)();

int fibonacci(int count)
{
    static std::vector<int> results{0, 1};

    if(count < static_cast<int>(results.size()) )
    {
        return results.at(static_cast<std::size_t>(count));
    }
    else{
        //    static int c{ 1 };
        //    std::cout << "fib "<< c << "-" << results.size() << '\n';
        //    c++;

        results.push_back(fibonacci(count-1) + fibonacci((count-2)));
        return results.at(static_cast<std::size_t>(count));
    }
}

int main()
{
    // 10.5		按值，引用和地址返回值
    std::tuple<int, double> s{ returnTuple() };
    std::cout << std::get<0>(s) << ' ' << std::get<1>(s) << '\n';

    // 10.9		功能指针
    std::function<int()> fcnPtr{ &foo };
    std::cout << fcnPtr() << '\n';

    OtherName fcnPtr2{ &foo };
    std::cout << (*fcnPtr2)() << fcnPtr2() << '\n';

    // 10.12		递归
//    记忆算法

//    上面的递归斐波那契算法效率不高，部分原因是每次对非基本情况的斐波那契调用都会导致另外两个斐波那契调用。这会产生指数级的函数调用（实际上，上面的示例调用fibonacci（）1205次！）。
//    有一些技术可用于减少必要的呼叫次数。
//            一种称为备忘录的技术可以缓存昂贵的函数调用的结果，以便当再次发生相同的输入时可以返回结果。
    for(int count = 0; count < 13; ++count)
        std::cout << fibonacci(count) << " ";

    return 0;
}
